﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Configuration;
using ServidorActividad;
using Eventos;

namespace ServidorConciliacion
{
    public class ConciliacionWCF:IConciliacionWCF
    {
        public void AgregarEvento(EventoDTO evento)
        {
            
            Container container = Container.GetInstancia();

            container.AgregarEvento(evento);

            //Console.WriteLine("Se recibio conexion con ID " + evento.IdSesion);
            Console.WriteLine("[CONCILIACION] Accion: " + evento.Comando.ToString() + ", IdSesion: " + evento.IdSesion.ToString() + ", Texto: " + evento.Texto);

        }


        public List<EventoDTO> ObtenerEventos()
        {
            String IP_RPC = ConfigurationManager.AppSettings["IP_RPC"];
            String PUERTO_RPC = ConfigurationManager.AppSettings["PUERTO_RPC"];

            TcpChannel chan = new TcpChannel();
            ChannelServices.RegisterChannel(chan, false);
            // Create an instance of the remote object
            //   remoteCalc = (ICalculator)Activator.GetObject(
            // )= typeof(ICalculator), "tcp://172.16.5.3:7000/Calculator");
            RemotingConfiguration.RegisterActivatedClientType(typeof(ActividadRPCImp), "tcp://"+IP_RPC+":"+PUERTO_RPC+"/ActividadRPCImp");

            ActividadRPCImp rpc=new ActividadRPCImp();

            List<EventoDTO> eventos = new List<EventoDTO>();

            foreach (Evento evnt in rpc.ObtenerEventos())
            {
                EventoDTO evento = new EventoDTO();
                evento.IdSesion = evnt.IdSesion;

                switch (evento.Comando.ToString())
                {
                    case "CONEXION": evento.Comando = EventoDTO.Comandos.CONEXION;
                        break;
                    case "CARGA": evento.Comando = EventoDTO.Comandos.CARGA;
                        break;
                    case "DESCONEXION": evento.Comando = EventoDTO.Comandos.DESCONEXION;
                        break;
                    case "DESCARGA": evento.Comando = EventoDTO.Comandos.DESCARGA;
                        break;
                }

                evento.IPCliente = evnt.IPCliente;
                evento.Texto = evnt.Texto;
                evento.Timestamp = evnt.Timestamp;

                eventos.Add(evento);

            }

            return eventos;
        }


        public List<string> Conciliar()
        {
            List<String> retorno = new List<String>();

            //Recorremos los eventos que tiene el servidor de conciliacion
            //y los compara con el servidor de actividad.

            List<EventoDTO> EventosActividad = ObtenerEventosActividad();

            retorno.Add("Primero comparamos los eventos que se encuentran en el servidor de conciliacion contra los registrados en el servidor de actividad.");
            foreach (EventoDTO e in ObtenerEventosDelContainer())
            {
                if(!(ExisteEventoEnLista(EventosActividad,e))){
                    //El evento e registrado por el servidor de conciliacion
                    //no se encuentra en el servidor de actividad
                    retorno.Add("El evento con ID de sesion " + e.IdSesion + " y comando " + e.Comando.ToString() + " fue registrado en conciliacion pero no en actividad.");

                }
            }

            if (retorno.Count == 1)
            {
                retorno.Add("Todos los eventos registrados en conciliacion se encuentran en el servidor de actividad.");
            }

            retorno.Add("****************************************************************************************************");
            retorno.Add("Ahora comparamos los eventos que se encuentran en el servidor de actividad contra los que estan en el servidor de conciliacion.");


            
            foreach (EventoDTO e in EventosActividad)
            {
                if (!(ExisteEventoEnLista(ObtenerEventosDelContainer(), e)))
                {
                    //El evento e registrado por el servidor de conciliacion
                    //no se encuentra en el servidor de actividad
                    retorno.Add("El evento con ID de sesion " + e.IdSesion + " y comando " + e.Comando.ToString() + " fue registrado en actividad pero no en conciliacion.");

                }
            }

            if (retorno.Count == 4)
            {
                retorno.Add("Todos los eventos registrados en actividad se encuentran en el servidor de conciliacion.");
            }

            return retorno;
        }

        private List<EventoDTO> ObtenerEventosDelContainer()
        {
            Container contenedor = Container.GetInstancia();

            return contenedor.ObtenerTodosLosEventos();
        }

        private List<EventoDTO> ObtenerEventosActividad()
        {

            String IP_RPC = ConfigurationManager.AppSettings["IP_RPC"];
            String PUERTO_RPC = ConfigurationManager.AppSettings["PUERTO_RPC"];

            TcpChannel chan = new TcpChannel();
            ChannelServices.RegisterChannel(chan, false);
            RemotingConfiguration.RegisterActivatedClientType(typeof(ActividadRPCImp), "tcp://" + IP_RPC + ":" + PUERTO_RPC + "/ActividadRPC");

            ActividadRPCImp rpc = new ActividadRPCImp();

            List<EventoDTO> EventosActividad = new List<EventoDTO>();


            foreach (Evento evnt in rpc.ObtenerEventos())
            {
                EventoDTO evento = new EventoDTO();
                evento.IdSesion = evnt.IdSesion;

                switch (evento.Comando.ToString())
                {
                    case "CONEXION": evento.Comando = EventoDTO.Comandos.CONEXION;
                        break;
                    case "CARGA": evento.Comando = EventoDTO.Comandos.CARGA;
                        break;
                    case "DESCONEXION": evento.Comando = EventoDTO.Comandos.DESCONEXION;
                        break;
                    case "DESCARGA": evento.Comando = EventoDTO.Comandos.DESCARGA;
                        break;
                }

                evento.IPCliente = evnt.IPCliente;
                evento.Texto = evnt.Texto;
                evento.Timestamp = evnt.Timestamp;

                EventosActividad.Add(evento);

            }

            return EventosActividad;
        }

        private bool ExisteEventoEnLista(List<EventoDTO> lista, EventoDTO evento)
        {
            bool retorno = false;

            foreach (EventoDTO evnt in lista)
            {
                if (String.Compare(evnt.IdSesion, evento.IdSesion)==0)
                {
                    if (String.Compare(evnt.IPCliente, evento.IPCliente) == 0)
                    {
                        if (String.Compare(evnt.Texto, evento.Texto) == 0)
                        {
                            if (String.Compare(evnt.Timestamp.ToString(), evento.Timestamp.ToString())==0)
                            {
                                retorno = true;
                            }
                            
                        }
                    }
                }
            }

            return retorno;
        }
    }
}
